package com.mxpio.erp.plan.mrp.policy.impl;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.Selection;

import org.springframework.stereotype.Component;

import com.mxpio.erp.common.enums.OrderEnums;
import com.mxpio.erp.common.inventory.entity.InvFlow;
import com.mxpio.erp.plan.mrp.Context;
import com.mxpio.erp.plan.mrp.CountModelMap;
import com.mxpio.erp.plan.mrp.bo.CountModel;
import com.mxpio.erp.plan.mrp.policy.LrpStoragePolicy;
import com.mxpioframework.common.util.BeanReflectionUtils;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.lin.Linq;

/**
 * 计算库存数量汇总
 * @author maxp
 *
 */
@Component
public class StoragePolicy extends LrpStoragePolicy {
	
	@Override
	public void apply(Context context) {
		// 计算库存数量汇总 ，通过context.setStorage(storage)方法返回
		Linq lin = JpaUtil.linq(InvFlow.class);
		List<String> fields = context.getItemIndexFields();
		Selection<?>[] selections = new Selection[fields.size()+3];
		String[] groupBys = new String[fields.size()+2];
		for(int i=0; i<fields.size(); i++){
			selections[i] = lin.root().get(fields.get(i));
			groupBys[i] = fields.get(i);
		}
		
		groupBys[fields.size()] = "itemCode";
		groupBys[fields.size()+1] = "accessType";
		selections[fields.size()] = lin.root().get("itemCode");
		selections[fields.size()+1] = lin.root().get("accessType");
		selections[fields.size()+2] = lin.criteriaBuilder().sum(lin.root().get("quantity")).alias("quantity");
		
		List<InvFlow> list = lin.select(selections)
				.groupBy(groupBys)
				.list();
		CountModelMap<CountModel> result = context.getStorage();
		for(InvFlow flow : list){
			Map<String,Object> entity = new HashMap<>();
			entity.put("itemCode",flow.getItemCode());
			for(int i=0; i<fields.size(); i++) {
				entity.put(fields.get(i), BeanReflectionUtils.getPropertyValue(flow, fields.get(i)));
			}
			if(flow.getQuantity() == null){
				flow.setQuantity(BigDecimal.ZERO);
			}
			if(OrderEnums.AccessType.IN.getCode().equals(flow.getAccessType())){
				entity.put("count", flow.getQuantity());
			}else{
				entity.put("count", BigDecimal.ZERO.subtract(flow.getQuantity()));
			}
			
			CountModel countModel = new CountModel((String) entity.get("itemCode"), (BigDecimal)entity.get("count"));
			indexProcessAdd(context, entity, result, countModel);
		}
		
		context.setStorage(result);
	}
 
	@Override
	public void after(Context context) {

	}
	
	/**
     * 递归计算所有组合
     * @param inputList 所有数组的列表，数组用List<String>存储
     * @param beginIndex 代表每一个数组的在inputList中的索引
     * @param fields 数组别名
     * @param arr 用于保存每一次递归生成的组合
     * @param result 结果
     * */
    public void calculateCombination(Map<String,List<String>> inputList, int beginIndex, Map<Integer,String> fields, String[] arr, List<Map<String,String>> result) {
        if(beginIndex == inputList.size()){
        	Map<String,String> map = new HashMap<>();
        	for (int k = 0 ; k < arr.length; k++) {
            	map.put(fields.get(k), arr[k]);
            }
        	result.add(map);
            return;
        }
        for(String c: inputList.get(fields.get(beginIndex))){
            arr[beginIndex] = c;
            calculateCombination(inputList, beginIndex + 1, fields, arr, result);
        }
    }

	@Override
	public void before(Context context) {
		Map<Integer, String> fields = new HashMap<Integer, String>();
		List<String> fieldlist = context.getItemIndexFields();
		for (int i = 0; i < fieldlist.size(); i++) {
			fields.put(i, fieldlist.get(i));
		}

		/*List<Map<String, String>> result = new ArrayList<Map<String, String>>();
		calculateCombination(dic, 0, fields, new String[dic.size()], result);
		String[] indexes = new String[result.size()];
		int i = 0;
		for(Map<String, String> map : result) {
			StringBuffer sb = new StringBuffer("");
			for(String field : fieldlist) {
				sb = sb.append(map.get(field)).append(",");
			}
			if(sb.length()>0) {
				sb.setLength(sb.length() - 1);
			}
			indexes[i] = sb.toString();
			i++;
		}*/
		
		CountModelMap<CountModel> storage = context.getStorage();
		for(String itemCode : context.getItems().keySet()) {
			Map<String,CountModel> modelMap = new HashMap<>();
			/*for(String index : indexes) {
				CountModel model = new CountModel();
				model.setCount(BigDecimal.ZERO);
				model.setItemCode(itemCode);
				model.setIndexes(index);
				modelMap.put(index, model);
			}*/
			CountModel model = new CountModel();
			model.setCount(BigDecimal.ZERO);
			model.setItemCode(itemCode);
			model.setIndexes("");
			modelMap.put("", model);
			storage.put(itemCode, modelMap);
		}
		context.setStorage(storage);
	}
}
